/******************************************************************************
 * $Id: menu.c,v 1.137 2004/11/27 00:36:38 jimb Exp $
 * @file
 * @author  Jim Brooks http://www.jimbrooks.org
 * @brief   Functions for menus.
 * @remarks A performance trick is to create a widget only once and use hide/show
 *          instead of recreating it.  However, if the widget has been pushed
 *          behind another widget, then the show function won't bring to the top.
 ******************************************************************************/
//#include <libgnomeprintui/gnome-print-job-preview.h>
//#include <gtksourceview/gtksourceprintcompositor.h>
#include "common.h"
#include "menu.h"

#include "sys.h"
#include "widgets.h"
#include "handlers.h"
#include "list.h"
#include "find.h"
#include "text.h"
#include "statusbar.h"
#include "popup.h"
#include "prefs.h"
#include "history.h"
#include "main.h"
#include "treefunc.h"

#include "handlers_module_opened.h"
#include "module_opened.h"
#include "i18n.h"

/*****************************************************************************
 * Set sensitivity of menubar.
 *****************************************************************************/
void
SetSensitivityMenubar( gboolean sensitive )
{
g_return_if_fail( pItemFactory );
#if 0
   /* --this won't work-- */
   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/Sort" ), sensitive );
#else

   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/View/Sort Tags by Name" ), sensitive );
   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/View/Sort Tags by Type" ), sensitive );
   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/View/Sort Tags by File" ), sensitive );

   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/Search/Find Text    F3" ), sensitive );
   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/Search/Find Tag     F4" ), sensitive );
   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/Search/Find File    F2" ), sensitive );

   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/Edit/Preference" ), sensitive );

   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/Help/Key Assignments" ), sensitive );
   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/Help/Release Notes" ), sensitive );
   gtk_widget_set_sensitive( gtk_item_factory_get_widget( pItemFactory, "/Help/About" ), sensitive );

#endif
}

void
cb_do_nothing(void)
{
    PrintStatusbar("*** Sorry, do nothing.");  
}


/*
 * set word wrop or not
 */
void
cb_WordWrap(void)
{
    if ( !IsTextWidgetEmpty() )
    {
        GtkWrapMode wrap;
        wrap = gtk_text_view_get_wrap_mode(GTK_TEXT_VIEW(pWidgetTextActive));
        if ( wrap != GTK_WRAP_NONE )
            gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(pWidgetTextActive),
                                         GTK_WRAP_NONE );
        else
            gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(pWidgetTextActive),
                                         GTK_WRAP_CHAR );
     }
}


/*
 * show/hide line number
 */
void
cb_LineNumber(void)
{
    if ( !IsTextWidgetEmpty() )
    {
        gboolean lineno ;
        lineno = gtk_source_view_get_show_line_numbers(GTK_SOURCE_VIEW(pWidgetTextActive));
        gtk_source_view_set_show_line_numbers( GTK_SOURCE_VIEW(pWidgetTextActive),
                                               !lineno );
    }
}

/******************************************************************************
 * Create the menubar.
 * @remarks "_Find" shouldn't be used because conventionally "F" is for "_File",
 * and "Alt+F" is used by the text widget (when it has the focus).
 ******************************************************************************/
void
CreateMenubar( GtkWidget* pWidgetHbox )
{
   static GtkItemFactoryEntry menuItems[] =
   {
      {N_("/_File"),					NULL,	0,			0,			"<Branch>"						},
      {N_("/File/_New"),         NULL,  G_CALLBACK(cb_new_file),    0,           0, 0},
 //    {N_("/File/Open"),       "<control>O",  G_CALLBACK(cb_do_nothing),   0,           0, 0},
      {N_("/File/_Close"),       NULL,  G_CALLBACK(cb_new_file),   0,           0, 0},
      {N_("/File/---"),             NULL,                  NULL,                                            0, "<Separator>"},
	  {N_("/File/_Save"),		"<control>S",G_CALLBACK(cb_save_file),    0,			"<StockItem>", GTK_STOCK_SAVE	},
      {N_("/File/Save as ..."),       NULL,  G_CALLBACK(cb_save_file_as),   0,          "<StockItem>", GTK_STOCK_SAVE_AS},
      {N_("/File/Save all"),       NULL,  G_CALLBACK(cb_save_all_file),   0,           0, 0},
      {N_("/File/---"),             NULL,                  NULL,                                            0, "<Separator>"},
//      {N_("/File/Print pre_view"),  NULL, G_CALLBACK(cb_PrintPreview),   0,           "<StockItem>", GTK_STOCK_PRINT_PREVIEW},
//      {N_("/File/_Print"),          NULL, G_CALLBACK(cb_PrintPreview),   0,           "<StockItem>", GTK_STOCK_PRINT},
      {N_("/File/---"),             NULL,                  NULL,                                            0, "<Separator>"},
  //    {N_("/File/Export to ..."),       NULL,  G_CALLBACK(cb_do_nothing),   0,           0, 0},
  //    {N_("/File/Import from ..."),       NULL,  G_CALLBACK(cb_do_nothing),   0,           0, 0},
  //    {N_("/File/Recent files"),		NULL,	0,			0,			"<Branch>"						},

	  {N_("/File/E_xit"),		"<control>Q",MenuItemSelected,		MENU_ITEM_FILE_EXIT,"<StockItem>" ,GTK_STOCK_QUIT 	},


      {N_("/_Edit"),                 NULL, 0,               0,             "<Branch>"                      },
      {N_("/Edit/_Undo"),        "<control>Z", G_CALLBACK(MenuItemSelected), MENU_ITEM_EDIT_UNDO, "<StockItem>", GTK_STOCK_UNDO },
      {N_("/Edit/_Redo"),        NULL,         G_CALLBACK(MenuItemSelected), MENU_ITEM_EDIT_REDO, "<StockItem>", GTK_STOCK_REDO },
      {N_("/Edit/---"),             NULL,                  NULL,                                            0, "<Separator>"},
      {N_("/Edit/Cut"),         "<control>X", G_CALLBACK(MenuItemSelected), MENU_ITEM_EDIT_CUT, "<StockItem>", GTK_STOCK_CUT },
      {N_("/Edit/Copy"),        "<control>C", G_CALLBACK(MenuItemSelected), MENU_ITEM_EDIT_COPY,"<StockItem>", GTK_STOCK_COPY },
      {N_("/Edit/Paste"),       "<control>V", G_CALLBACK(MenuItemSelected), MENU_ITEM_EDIT_PASTE,"<StockItem>", GTK_STOCK_PASTE },
//      {N_("/Edit/Delete"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Edit/Select all"),  "<control>A", G_CALLBACK(MenuItemSelected), MENU_ITEM_EDIT_SELECT_ALL, 0, 0 },
      {N_("/Edit/---"),             NULL,                  NULL,                               0, "<Separator>"},
      {N_("/Edit/Goto line..."),        "<control>J", G_CALLBACK(GotoLine), 0, 0, 0 },
//      {N_("/Edit/Bookmark"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
//      {N_("/Edit/Next Bookmark"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
//      {N_("/Edit/Clear Bookmarks"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
//      {N_("/Edit/Comment"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
//      {N_("/Edit/Uncomment"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
//      {N_("/Edit/Insert code"),        NULL, 0 , 0, "<Branch>"},
      {N_("/Edit/Goto Definition"),        NULL, G_CALLBACK(HandlerToolbarButtonGotoTag), 0, 0, 0 },
      {N_("/Edit/Goto Reference"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Edit/---"),             NULL,                  NULL,                               0, "<Separator>"},
      {N_("/Edit/Pref_erence"), NULL, MenuItemSelected, MENU_ITEM_PREFS_EDIT, "<StockItem>", GTK_STOCK_PREFERENCES},


      {N_("/_View"),                 NULL, 0,               0,             "<Branch>"                      },
//      {N_("/View/Toolbar"),        NULL, 0, 0, "<Branch>" },
      {N_("/View/Word Wrap"),      NULL, G_CALLBACK(cb_WordWrap),0,0,0},
      {N_("/View/Line Numbers"),      NULL, G_CALLBACK(cb_LineNumber),0,0,0},
//      {N_("/View/Statusbar"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
//      {N_("/View/Filesbar"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
//      {N_("/View/Tags bar"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
//      {N_("/View/ModuleTree bar"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/View/---"),             NULL,                  NULL,                               0, "<Separator>"},
      {N_("/View/Sort Tags by Name"),    NULL,	MenuItemSelected,MENU_ITEM_SORT_TAG,			0   },
      {N_("/View/Sort Tags by Type"),      NULL,	MenuItemSelected,MENU_ITEM_SORT_TYPE,		0   },
      {N_("/View/Sort Tags by File"),        NULL,	MenuItemSelected,MENU_ITEM_SORT_MODULE,		0   },


      {N_("/_Search"),					NULL,	0,			0,			"<Branch>"		},
      {N_("/Search/Find _File    F2"),		NULL,MenuItemSelected,MENU_ITEM_FIND_MODULE,		0  	},
      {N_("/Search/Find Te_xt    F3"),	NULL,	MenuItemSelected,MENU_ITEM_FIND_TEXT,		0  	},
      {N_("/Search/Find _Tag     F4"),	NULL,	MenuItemSelected,MENU_ITEM_FIND_TAG,			0  	},

      
/*
      {N_("/_Project"),                 NULL, 0,               0,             "<Branch>" },
      {N_("/Project/Create Project"),  NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Project/Open Project"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Project/Close Project"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Project/Recent Projects"),		NULL,	0,			0,			"<Branch>"	},
      
      {N_("/_CVS"),                 NULL, 0,               0,             "<Branch>"  },
      {N_("/CVS/Check in"),  NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/CVS/Check out"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/CVS/Configure cvs"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },

      {N_("/_Build"),                 NULL, 0,               0,             "<Branch>" },
      {N_("/Build/Build Project"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Build/Rebuild all"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Build/Stop Build"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Build/Configure Build"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },


      {N_("/_Tools"),                 NULL, 0,               0,             "<Branch>"  },
      {N_("/Tools/Configure Compiler"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Tools/Configure other tools"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },

      {N_("/_Window"),                 NULL, 0,               0,             "<Branch>" },
      {N_("/Window/Close"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Window/Close all"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Window/Opened windows(10)"),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
      {N_("/Window/Window list ..."),        NULL, G_CALLBACK(cb_do_nothing), 0, 0, 0 },
*/

      {N_("/_Help"),					NULL,	0,			0,			"<Branch>"	},
      {N_("/Help/_Key Assignments"),	NULL,	MenuItemSelected,		MENU_ITEM_HELP_KEYS,		0   },
      {N_("/Help/_Release Notes"),		NULL,	MenuItemSelected,		MENU_ITEM_HELP_NOTES,		0   },
      {N_("/Help/_About"),				NULL,	MenuItemSelected,		MENU_ITEM_HELP_ABOUT,		"<StockItem>", GTK_STOCK_ABOUT   },
      {N_("/Help/devhelp      F1"),	NULL,	MenuItemSelected,		MENU_ITEM_HELP_SEARCH,		0   }
   };
   
  /*
   * Create a new accel group.
   */
   pAccelGroup = gtk_accel_group_new();

  /*
   * Create a new item factory.
   */
   pItemFactory = gtk_item_factory_new( GTK_TYPE_MENU_BAR,
                                        "<main>",
                                        pAccelGroup );
  /*
   * Set translate funcs for i18n.
   */
   gtk_item_factory_set_translate_func(pItemFactory, MenuTranslate, NULL, NULL);
  /*
   * Create the items in the factory.
   */
   gtk_item_factory_create_items( pItemFactory,
                                  sizeof(menuItems) / sizeof(menuItems[0]),
                                  menuItems,
                                  NULL );
  /*
   * Attach the accel group to the main window.
   */
   gtk_window_add_accel_group(GTK_WINDOW(pWidgetMain),
                         pAccelGroup);
//   gtk_accel_group_attach( pAccelGroup,
//                           GTK_OBJECT(pWidgetMain) ); //lv

  /*
   * Put the menubar in the hbox.
   */
   gtk_box_pack_start( GTK_BOX( pWidgetHbox ),
                       gtk_item_factory_get_widget( pItemFactory,
                                                    "<main>" ),
                       FALSE, FALSE, 0 );

   return;
}


/******************************************************************************
 * Callback for when a menu item is selected.
 ******************************************************************************/
void
MenuItemSelected( gpointer   pData,
                  guint      menuItem,
                  GtkWidget* pWidget )
{
  /*
   * Prevent nesting major functions.
   */
   if ( IsAnyMajorFunctionBusy(TRUE) ) return;

  /*
   * Clear the statusbar before calling a menu item function.
   * Often, lingering statusbar messages are no longer relevant, and can cause confusion.
   */
   MostlyClearStatusbar();

  /*
   * Route the menu item to the appropriate function.
   */
   switch ( menuItem )
   {
      case MENU_ITEM_FILE_EXIT:

        
             if ( IsMainModuleModified() )
        	 {
		        //Save changes to `file'?
		        // No, Cancel, Yes
		        gint result = AskSaveOrNot();
		        if ( result == GTK_RESPONSE_YES || 
		             result == GTK_RESPONSE_NO )
		        {
		            SaveVars();
		            gtk_main_quit();
		        }
		        else
		            return ;
	          }
	          else
	          {
	              SaveVars();
	              gtk_main_quit();
	          }
         break;

      case MENU_ITEM_FIND_TAG:
         CreateFindDialog( MENU_ITEM_FIND_TAG );
         break;

      case MENU_ITEM_FIND_TEXT:
         CreateFindDialog( MENU_ITEM_FIND_TEXT );
         break;

      case MENU_ITEM_FIND_MODULE:
         CreateFindDialog( MENU_ITEM_FIND_MODULE );
         break;

      case MENU_ITEM_SORT_TAG:
         SetSensitivityWhileBusy( FALSE );
         PopulateTagsClistWidget( SORT_TAG );
         SetSensitivityWhileBusy( TRUE );
         break;

      case MENU_ITEM_SORT_MODULE:
         SetSensitivityWhileBusy( FALSE );
         PopulateTagsClistWidget( SORT_MODULE );
         SetSensitivityWhileBusy( TRUE );
         break;

      case MENU_ITEM_SORT_TYPE:
         SetSensitivityWhileBusy( FALSE );
         PopulateTagsClistWidget( SORT_TYPE );
         SetSensitivityWhileBusy( TRUE );
         break;
 
      case MENU_ITEM_PREFS_EDIT:
         EditPrefs();
         break;

         break;

      case MENU_ITEM_EDIT_CUT:

         if ( pWidgetTextActive == pWidgetTextMain )
            g_signal_emit_by_name(pWidgetTextActive,"cut-clipboard");
         break;
      case MENU_ITEM_EDIT_COPY:
         g_signal_emit_by_name(pWidgetTextActive,"copy-clipboard");
         break;
      case MENU_ITEM_EDIT_PASTE:
         if ( pWidgetTextActive == pWidgetTextMain )
            g_signal_emit_by_name(pWidgetTextActive,"paste-clipboard");
         break;

      case MENU_ITEM_EDIT_UNDO:
         if ( pWidgetTextActive == pWidgetTextMain )
            g_signal_emit_by_name(pWidgetTextActive, "undo");
         break;

      case MENU_ITEM_EDIT_REDO:
         if ( pWidgetTextActive == pWidgetTextMain )
            g_signal_emit_by_name(pWidgetTextActive, "redo");
         break;

      case MENU_ITEM_EDIT_SELECT_ALL:
          g_signal_emit_by_name(pWidgetTextActive,"select-all");
          break;

      case MENU_ITEM_HELP_SEARCH:
         RunHelper();   // 查找当前光标处的单词，并且在 devhelp 中显示
         break;
      case MENU_ITEM_HELP_KEYS:
/*
 * the default N_ has an err 
 */
#ifdef N_
#undef N_
#endif
#define N_(string)  string

         Popup( N_("   ---------------------------------------------------------- \n"
                "   F3 or Ctrl+F       find text (opens dialog)                \n"
                "   F4                 find tag  (opens dialog)                \n"
                "   F5 or Ctrl+Enter/D goto tag  (under cursor)                \n"
                "   F6                 to earlier tag  (in history)            \n"
                "   F7                 to later   tag  (in history)            \n"
                "   F8                 find strings matching one under cursor  \n"
                "   F9                 record cursor position in history       \n"
                "   Ctrl+N or Ctrl+G   find next text/tag (forward)            \n"
                "   Ctrl+R             find next text/tag (backward)           \n"
                "   Ctrl+L             re-center text view                     \n"
                "   Left-Shift         hyperjump using bottom text view        \n"
                "   Left-Ctrl          disable updating tree                   \n"
                "   ---------------------------------------------------------- \n"),
                _("Default Key Assignments"),
                FONT_PROPORTIONAL );
         break;

      case MENU_ITEM_HELP_ABOUT:
         Popup( "hypersrc\n\n" "5.4.18" " by Jim E. Brooks\nwww.jimbrooks.org/hypersrc/\n\n" \
                "6.0-beta1 by   Lvjinhua\nHomepage: http://www.dubuntu.com/hypersrc\n" \
                "Maillist: http://groups.google.com/group/hypersrc\n\n" LICENSE_BRIEF_STR ,
                _("About hypersrc"),
                FONT_PROPORTIONAL );
         break;

      case MENU_ITEM_HELP_NOTES:
#if defined(HYPERSRC_DEBUG)
 #ifdef HYPERSRC_PEDANTIC
 #define BINARY_BUILD	"DEBUG (pedantic)"
 #else
 #define BINARY_BUILD	"DEBUG"
 #endif
#elif defined(HYPERSRC_SPEED)
 #define BINARY_BUILD	"SPEED"
#else /* assume release */
 #ifndef G_DISABLE_ASSERT
 #define BINARY_BUILD	"RELEASE"
 #else
 #define BINARY_BUILD	"RELEASE (asserts disabled)"
 #endif
#endif

#ifdef HYPERSRC_PROFILE
#define BINARY_BUILD_PROFILE "PROFILE/"
#else
#define BINARY_BUILD_PROFILE ""
#endif
         {
         static char releaseNotes[] =
         N_("Version ") HYPERSRC_VERSION_STRING
         "\n\n" BINARY_BUILD_PROFILE BINARY_BUILD N_(" build.")
         N_("\n\nTested on ( 5.4.18 ):\nRedhat 8, Mandrake 8.1, Debian 3, FreeBSD 4.6.2\nGTK+ 1.2.10\nXFree86 4.x.x")\
         N_("\n\nTested on ( ") HYPERSRC_VERSION_STRING N_(" ): Dubuntu-6.06, Ubuntu-6.06\nGTK+ 2.4\nXorg-7.0\n");
         Popup( releaseNotes, _("Release notes"), FONT_PROPORTIONAL );
         }
         //N_("\n\nTested on:\nRedhat 8, Mandrake 8.1, Debian 3, FreeBSD 4.6.2\nGTK+ 1.2.10\nXFree86 4.x.x");
         break;
   }

   return;
}


#if 0
static void
cb_PrintPreviewFinished(GtkSourcePrintCompositor *job, gpointer title)
{
    GtkWidget *pPrintPreview = NULL;
    GnomePrintJob     *print_job;
    //print_job = gtk_source_print_compositor_print(job);
    print_job = gtk_source_print_compositor_get_print_job(job);
    pPrintPreview = gnome_print_job_preview_new( print_job,
                        (const guchar*)(title));
    g_object_unref(print_job);
    g_object_unref(job);
    gtk_widget_show(pPrintPreview);
}

static void
GetPrintJobFromView(GtkTextView *textView, gchar * title)
{
    GtkSourcePrintCompositor *job;
    GtkTextBuffer     *pTextBuf = NULL;

    g_return_if_fail(textView != NULL);
    job = gtk_source_print_compositor_new(NULL);
    gtk_source_print_compositor_new_from_view(job, GTK_SOURCE_VIEW(textView));
//    gtk_source_print_compositor_set_print_numbers(job,5);
    gtk_source_print_compositor_set_wrap_mode(job,GTK_WRAP_CHAR);
    gtk_source_print_compositor_set_tab_width(job, 4);
    gtk_source_print_compositor_set_header_footer_font(job,"Serif Regular 11");
    gtk_source_print_compositor_set_header_format(job,
                                           NULL, //left
                                           title,//center
                                           NULL, //right
                                           TRUE);//separator
    gtk_source_print_compositor_set_print_header(job, TRUE);
    gtk_source_print_compositor_set_footer_format(job,
                                           _("Printed on %F %T %A"),
                                           NULL,
                                           _("Page %N/%Q"),
                                           TRUE);
    gtk_source_print_compositor_set_print_footer(job, TRUE);
    
    GtkTextIter start, end;
    
    pTextBuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textView));
    
    gtk_text_buffer_get_bounds(pTextBuf, &start, &end);
    
    if ( gtk_source_print_compositor_print_range_async(job, &start, &end))
    {
        g_signal_connect(job, "finished", G_CALLBACK(cb_PrintPreviewFinished),
                         _("Hypersrc print preview"));
    }
    else
    {
        PrintStatusbar(_("**Async print job fail."));
        return ;
    }

    return ;
}

#endif
#if 0
void
cb_PrintPreview(gpointer data,
        guint menuItem,
        GtkWidget * pWidget)
{
    //  
    if ( IsTextWidgetEmpty() || !ActiveModule() )
    {
        PrintStatusbar(_("Text Widget is empty"));
        return;
    }
    if ( IsAnyMajorFunctionBusy(TRUE) )
        return;
    
    // set busy mode TRUE

    GetPrintJobFromView(GTK_TEXT_VIEW(pWidgetTextActive), 
                      ActiveModuleName());
    // set busy mode FALSE
}
#endif

/*****************************************************************************
 * Run an editor (vi/emacs/xemacs).
 *****************************************************************************/
void
RunEditor( char* pEditor )
{
   char*	execArgs[10];
   int		line;
   char		arg[20];

   if ( IsTextWidgetEmpty()  ||  ! ActiveModule() )
   {
      PrintStatusbar( _("Text widget is empty") );
      return;
   }
g_return_if_fail( ActiveModule()->pModuleName );

  /*
   * Compute the goto-line arg +nnn which is the same in vi/emacs/xemacs.
   */
   line = LineAtCursor() + 1;
   if ( line <= 2 ) line = 1;
   sprintf( arg, "+%d", line );

   if ( strstr( pEditor, "emacs" ) )
   {
     /*
      * emacs/xemacs
      */
      execArgs[0] = pEditor;
      execArgs[1] = arg;
      execArgs[2] = ActiveModule()->pModuleName;
      execArgs[3] = NULL;
   }
   else
   {
     /*
      * vi/vim
      * Run via a separate xterm.
      */
      execArgs[0] = "xterm";
      execArgs[1] = "-tn";			/* export TERM=xterm-color so that vim can show colors */
      execArgs[2] = "xterm-color";
      execArgs[3] = "-e";
      execArgs[4] = pEditor;
      execArgs[5] = arg;
      execArgs[6] = ActiveModule()->pModuleName;
      execArgs[7] = NULL;
   }

   SysExec( execArgs[0], execArgs );

   return;
}

/*****************************************************************************
 * Run devhelp when press F1 or Help menu.
 *****************************************************************************/
void
RunHelper(void)
{
    if ( !devhelpExists )
    {
        PrintStatusbar(_("*** devhelp not found"));
        return;
    }

    if ( IsAnyMajorFunctionBusy(TRUE))
    {
        return;
    }
    else
    if ( IsTextWidgetEmpty() || !ActiveModule() )
    {
        PrintStatusbar(_("Text widget is empty."));
        return;
    }
    gsize textLen = 0;
    gchar *pText = ActiveTextWidgetContents(&textLen);
    gint cursorIdx = OffsetAtCursor();
    if( cursorIdx < 0 || cursorIdx > textLen )
        return;

    // howto detect 'devehlp' exist?
    GString *wordAtCursor = ScoopWordAtCursor(MAX_WORD_LEN,
                            pText,
                            textLen,
                            cursorIdx);
    if ( NULL == wordAtCursor )
        return;

    gchar* sysargs[20]; // may be enough
    sysargs[0]="devhelp";
    sysargs[1]="--search";
    sysargs[2]=g_strdup(wordAtCursor->str);
    sysargs[3]=NULL;
    
    /*
     *run the helper and search 'str'
     */
    SysExec(sysargs[0], sysargs);
    
    g_string_free(wordAtCursor, TRUE);
    return;
}

/*****************************************************************************
 * Create/show the dialog widget for finding.
 * The find dialog is used for finding either a tag or a text string.
 * @param   menuItem (GLOBAL)
 *          Which menu item corresponds to the dialog widget.
 *          Can be one of MENU_ITEM_FIND_*.
 * @param   pWidgetDialogFind (IO/GLOBAL)
 *          Pointer to the create (or recreated) dialog widget.
 *****************************************************************************/
void
CreateFindDialog( MENU_ITEM menuItem )
{
   GtkWidget*	pWidgetHbox             = NULL;		/* contains all boxes */
   GtkWidget*	pWidgetVboxButtons      = NULL;		/* contains rows of buttons */
   GtkWidget*	pWidgetVboxEntryWord    = NULL;		/* contains text entry and "Word At Cursor" button */
   GtkWidget*	pWidgetHboxEntry        = NULL;		/* contains text entry and its label */
   GtkWidget*	pWidgetLabel            = NULL;
   GtkWidget*   pWidgetButtonWord       = NULL;
   GtkWidget*   pWidgetButtonRestoreCursor = NULL;
   GtkWidget*	pWidgetButtonFind       = NULL;
   GtkWidget*	pWidgetButtonCancel     = NULL;
   GString**	ppSought                = NULL;

  /*
   * Record what kind of item is sought (ie a tag or text string)
   * for the next find.
   */
   soughtType = menuItem;

  /*
   * Save the cursor position in the text widget in case later
   * the user wants to restore the cursor position after doing searches.
   */
   SaveCursor( &cursorText );

  /*
   * Destroy the widget if it is already created.
   */
   if ( pWidgetDialogFind ) gtk_widget_destroy( pWidgetDialogFind );

  /*
   * Create (recreate) the dialog widget.
   */
   pWidgetDialogFind = gtk_dialog_new();
   //gtk_window_set_modal(GTK_WINDOW(pWidgetDialogFind), TRUE);
   gtk_window_set_transient_for(GTK_WINDOW(pWidgetDialogFind),
                                GTK_WINDOW(pWidgetMain));

  /*
   * Install key event handlers (to close dialog if ESC is pressed).
   */
   g_signal_connect( G_OBJECT(pWidgetDialogFind),
                       "key-press-event",
                       G_CALLBACK(HandlerKeyPressDialogFind),
                       NULL );
   g_signal_connect( G_OBJECT(pWidgetDialogFind),
                       "key-release-event",
                       G_CALLBACK(HandlerKeyRelease),
                       NULL );
   gtk_widget_add_events( pWidgetDialogFind,
                          GDK_KEY_RELEASE_MASK );	/* to enable key release events */

  /*
   * Init appropriate vars.
   */
   if ( soughtType == MENU_ITEM_FIND_TAG )
      ppGlistFindStrings = &pGlistFindStringsTag;
   else
   if ( soughtType == MENU_ITEM_FIND_TEXT )
      ppGlistFindStrings = &pGlistFindStringsText;
   else
   if ( soughtType == MENU_ITEM_FIND_MODULE )
      ppGlistFindStrings = &pGlistFindStringsModule;
   else
      g_return_if_fail( 0 );

  /*
   * Title the dialog.
   */
   if ( soughtType == MENU_ITEM_FIND_TAG )
      gtk_window_set_title( GTK_WINDOW(pWidgetDialogFind),
                            _("Find Tag" ));
   else
   if ( soughtType == MENU_ITEM_FIND_TEXT )
      gtk_window_set_title( GTK_WINDOW(pWidgetDialogFind),
                            _("Find Text" ));
   else
   if ( soughtType == MENU_ITEM_FIND_MODULE )
      gtk_window_set_title( GTK_WINDOW(pWidgetDialogFind),
                            _("Find Module" ));
   else
      g_return_if_fail( 0 );

  /*
   * Widen the border of the dialog.
   */
   gtk_container_border_width( GTK_CONTAINER(pWidgetDialogFind),
                               16 );

  /*
   * Create/pack the various boxes.
   */
   pWidgetHbox          = gtk_hbox_new( FALSE, 4 );
   pWidgetHboxEntry     = gtk_hbox_new( FALSE, 4 );
   pWidgetVboxEntryWord = gtk_vbox_new( FALSE, 4 );
   pWidgetVboxButtons   = gtk_vbox_new( TRUE,  4 );
   gtk_box_pack_start( GTK_BOX(pWidgetHbox),			/* pack textEntry/word's vbox into main hbox */
                       pWidgetVboxEntryWord,
                       TRUE, TRUE, 4 );
   gtk_box_pack_start( GTK_BOX(pWidgetVboxEntryWord),	/* pack textEntry's hbox into textEntry/word vbox */
                       pWidgetHboxEntry,
                       TRUE, TRUE, 4 );
   gtk_box_pack_end( GTK_BOX(pWidgetHbox),				/* pack buttons's vbox into main hbox */
                     pWidgetVboxButtons,
                     TRUE, TRUE, 4 );

  /*
   * Create/pack a label for the dialog.
   */
   if ( soughtType == MENU_ITEM_FIND_TAG )
      pWidgetLabel = gtk_label_new(_( "Find (fuzzy): " ));
   else
   if ( soughtType == MENU_ITEM_FIND_TEXT )
      pWidgetLabel = gtk_label_new(_( "Find: " ));
   else
   if ( soughtType == MENU_ITEM_FIND_MODULE )
      pWidgetLabel = gtk_label_new( _("Find (fuzzy): ") );
   else
      g_return_if_fail( 0 );

   gtk_box_pack_start( GTK_BOX(pWidgetHboxEntry),
                       pWidgetLabel,
                       TRUE, TRUE, 4 );

  /*
   * Create/pack the combo (text entry field) of the dialog.
   * Do not add pop-down strings if no search has even been done before.
   * gtk_combo_disable_active() makes Enter key work as expected.
   */
   pWidgetComboFind = gtk_combo_new();
   gtk_combo_disable_activate( GTK_COMBO(pWidgetComboFind) );
   if ( *ppGlistFindStrings != NULL )
      gtk_combo_set_popdown_strings( GTK_COMBO(pWidgetComboFind),
                                     *ppGlistFindStrings );
   gtk_box_pack_start( GTK_BOX(pWidgetHboxEntry),
                       pWidgetComboFind,
                       TRUE, TRUE, 4 );

  /*
   * By default, a combo's entry widget will try to alter the case
   * of a newly entered string to match a previous string.
   * Such behavior is a hindrance in a find dialog, so disable it.
   */
   gtk_combo_set_value_in_list( GTK_COMBO(pWidgetComboFind),
                                FALSE,
                                FALSE );
   gtk_combo_set_case_sensitive( GTK_COMBO(pWidgetComboFind),
                                 TRUE );

  /*
   * Insert the previous appropriate sought item (if it exists)
   * into the text entry (to facilitate repeated searches for same item).
   */
   if ( soughtType == MENU_ITEM_FIND_TAG )
      ppSought = &pSoughtTag;
   else
   if ( soughtType == MENU_ITEM_FIND_TEXT )
      ppSought = &pSoughtText;
   else
   if ( soughtType == MENU_ITEM_FIND_MODULE )
      ppSought = &pSoughtModule;
   else
      g_return_if_fail( 0 );

   if ( *ppSought )
      gtk_entry_set_text( GTK_ENTRY( GTK_COMBO(pWidgetComboFind)->entry ),
                          (*ppSought)->str );

  /*
   * For text search, create/pack the "Word At Cursor" button (underneath the text entry).
   */
 /* // 在任何情况下都显示 "Word At Cursor“的按钮！
   if (     soughtType == MENU_ITEM_FIND_TEXT
        &&  ! IsTextWidgetEmpty()
        &&  IsCursorOverWord() )
*/
   if ( 1 )
   {
     /*
      * Create/pack "Word At Cursor" button.
      */
      pWidgetButtonWord = gtk_button_new_with_mnemonic(_("Choose _Word at Cursor"));

      gtk_box_pack_start( GTK_BOX(pWidgetVboxEntryWord),
                        pWidgetButtonWord,
                        TRUE, FALSE, 4 );

     /*
      * Connect to signal when "Word At Cursor" is clicked.
      */
      gtk_signal_connect( GTK_OBJECT(pWidgetButtonWord),
                          "clicked",
                          GTK_SIGNAL_FUNC(WordAtCursorClicked),
                          NULL );

     /*
      * For key handler, remember that this button was created.
      */
      buttonWordAtCursorFlag = TRUE;
   }

  /*
   * Create a button to restore the cursor position.
   */
   if ( ! IsTextWidgetEmpty() )
   {
      pWidgetButtonRestoreCursor = \
      gtk_button_new_with_mnemonic( _("Restore Cursor _Position"));

      gtk_box_pack_start( GTK_BOX(pWidgetVboxEntryWord),
                          pWidgetButtonRestoreCursor,
                          TRUE, FALSE, 4 );
      gtk_signal_connect( GTK_OBJECT(pWidgetButtonRestoreCursor),
                          "clicked",
                          GTK_SIGNAL_FUNC(RestoreCursorClicked),
                          NULL );
     /*
      * For key handler, remember that this button was created.
      */
      buttonRestoreCursorFlag = TRUE;
   }

  /*
   * Create appropriate buttons and connect to appropriate signals.
   *
   * Create/pack the appropriate check buttons.
   */
   if ( soughtType == MENU_ITEM_FIND_TEXT )
   {
      pWidgetCheckButtonFindGlobal  = gtk_check_button_new_with_label(_( "global" ));
      pWidgetCheckButtonFindExact   = NULL;
      pWidgetCheckButtonFindCase    = gtk_check_button_new_with_label(_( "case-sensitive") );
      pWidgetCheckButtonFindReverse = gtk_check_button_new_with_label(_( "reverse" ));
      pWidgetCheckButtonFindRegex   = gtk_check_button_new_with_label(_( "regex" ));
   }
   else /* find tag or module */
   {
      pWidgetCheckButtonFindGlobal  = NULL;
      pWidgetCheckButtonFindExact   = gtk_check_button_new_with_label(_( "exact match" ));
      pWidgetCheckButtonFindCase    = gtk_check_button_new_with_label(_( "case-sensitive" ));
      pWidgetCheckButtonFindReverse = NULL;
      pWidgetCheckButtonFindRegex   = NULL;
   }

   if ( pWidgetCheckButtonFindGlobal )
      gtk_box_pack_start( GTK_BOX(pWidgetVboxButtons),
                          pWidgetCheckButtonFindGlobal,
                          TRUE, TRUE, 0 );
   if ( pWidgetCheckButtonFindExact )
      gtk_box_pack_start( GTK_BOX(pWidgetVboxButtons),
                          pWidgetCheckButtonFindExact,
                          TRUE, TRUE, 0 );
   if ( pWidgetCheckButtonFindCase )
      gtk_box_pack_start( GTK_BOX(pWidgetVboxButtons),
                          pWidgetCheckButtonFindCase,
                          TRUE, TRUE, 0 );
   if ( pWidgetCheckButtonFindReverse )
      gtk_box_pack_start( GTK_BOX(pWidgetVboxButtons),
                          pWidgetCheckButtonFindReverse,
                          TRUE, TRUE, 0 );
   if ( pWidgetCheckButtonFindRegex )
      gtk_box_pack_start( GTK_BOX(pWidgetVboxButtons),
                          pWidgetCheckButtonFindRegex,
                          TRUE, TRUE, 0 );

  /*
   * Depress the check button if "exact match" was previously selected.
   */
   if (    (soughtType == MENU_ITEM_FIND_TAG     &&  findExactTag)
        || (soughtType == MENU_ITEM_FIND_MODULE  &&  findExactModule) )
      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(pWidgetCheckButtonFindExact),
                                    TRUE );

  /*
   * Depress the check button if "case-sensitive" was previously selected.
   */
   if (    (soughtType == MENU_ITEM_FIND_TEXT    &&  findCaseSensText)
        || (soughtType == MENU_ITEM_FIND_TAG     &&  findCaseSensTag)
        || (soughtType == MENU_ITEM_FIND_MODULE  &&  findCaseSensModule) )
      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(pWidgetCheckButtonFindCase),
                                    TRUE );

  /*
   * Depress the check button if "reverse".
   */
   if (    (soughtType == MENU_ITEM_FIND_TEXT    &&  findReverse) )
      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(pWidgetCheckButtonFindReverse),
                                    TRUE );

  /*
   * Depress the check button if "regex".
   */
   if (    (soughtType == MENU_ITEM_FIND_TEXT    &&  regex) )
      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(pWidgetCheckButtonFindRegex),
                                    TRUE );

  /*
   * Depress the check button if "global" was previously selected.
   */
   if ( soughtType == MENU_ITEM_FIND_TEXT  &&  findGlobal )
      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(pWidgetCheckButtonFindGlobal),
                                    TRUE );

  /*
   * Connect to the "toggle" signal for check buttons.
   */
   if ( pWidgetCheckButtonFindExact )
      gtk_signal_connect( GTK_OBJECT(pWidgetCheckButtonFindExact),
                          "toggled",
                          GTK_SIGNAL_FUNC(CheckButtonFindToggledBool),
                          soughtType == MENU_ITEM_FIND_TAG ? &findExactTag : &findExactModule );
   if ( pWidgetCheckButtonFindCase )
      gtk_signal_connect( GTK_OBJECT(pWidgetCheckButtonFindCase),
                          "toggled",
                          GTK_SIGNAL_FUNC(CheckButtonFindToggledBool),
                          soughtType == MENU_ITEM_FIND_TEXT ? &findCaseSensText : soughtType == MENU_ITEM_FIND_TAG ? &findCaseSensTag : &findCaseSensModule );
   if ( pWidgetCheckButtonFindGlobal )
      gtk_signal_connect( GTK_OBJECT(pWidgetCheckButtonFindGlobal),
                          "toggled",
                          GTK_SIGNAL_FUNC(CheckButtonFindGlobalToggled),
                          NULL );
   if ( pWidgetCheckButtonFindReverse )
      gtk_signal_connect( GTK_OBJECT(pWidgetCheckButtonFindReverse),
                          "toggled",
                          GTK_SIGNAL_FUNC(CheckButtonFindReverseToggled),
                          NULL );
   if ( pWidgetCheckButtonFindRegex )
      gtk_signal_connect( GTK_OBJECT(pWidgetCheckButtonFindRegex),
                          "toggled",
                          GTK_SIGNAL_FUNC(CheckButtonFindRegexToggled),
                          NULL );

  /*
   * Create/pack the "Find" button.
   */
   pWidgetButtonFind = gtk_button_new_with_mnemonic(_( "_Find" ));

   gtk_box_pack_start( GTK_BOX(GTK_DIALOG(pWidgetDialogFind)->action_area),
                       pWidgetButtonFind,
                       TRUE, TRUE, 0 );

  /*
   * Make the Find button the default button.
   */
   GTK_WIDGET_SET_FLAGS( pWidgetButtonFind,
                         GTK_CAN_DEFAULT );
   gtk_widget_grab_default( pWidgetButtonFind );

  /*
   * Create/pack the "Cancel" button.
   */
   pWidgetButtonCancel = gtk_button_new_with_label(_("Close" ));
   gtk_box_pack_start( GTK_BOX(GTK_DIALOG(pWidgetDialogFind)->action_area),
                       pWidgetButtonCancel,
                       TRUE, TRUE, 0 );

  /*
   * The final pack is to pack the hbox into the dialog's vbox.
   */
   gtk_box_pack_start( GTK_BOX(GTK_DIALOG(pWidgetDialogFind)->vbox),
                       pWidgetHbox,
                       TRUE, TRUE, 0 );

  /*
   * Connect to signals.
   */
   gtk_signal_connect( GTK_OBJECT(pWidgetDialogFind),
                       "destroy",
                       GTK_SIGNAL_FUNC(FindDialogClose),
                       NULL );
   gtk_signal_connect( GTK_OBJECT(pWidgetButtonFind),
                       "clicked",
                       GTK_SIGNAL_FUNC(FindDialogClickedFind),
                       NULL );
   gtk_signal_connect( GTK_OBJECT(pWidgetButtonCancel),
                       "clicked",
                       GTK_SIGNAL_FUNC(FindDialogClose),
                       NULL );

  /*
   * Position/show the dialog (and its sub-widgets).
   */
   PositionShowFindDialog( pWidgetDialogFind );

  /*
   * Grab the focus for the entry widget.
   */
   gtk_widget_grab_focus( GTK_WIDGET(GTK_COMBO(pWidgetComboFind)->entry) );

   return;
}

/*****************************************************************************
 * Called when the find dialog is closed/canceled.
 *****************************************************************************/
void
FindDialogClose( void )
{
  /*
   * This will be called twice if user clicks close before search completes.
   */
   if ( pWidgetDialogFind == NULL ) return;

  /*
   * Record the geom of the find dialog, to be used next time.
   */
   if ( pWidgetDialogFind->window )
   {
      WidgetGeom( pWidgetDialogFind,
                  &findGeom[0],
                  &findGeom[1],
                  &findGeom[2],
                  &findGeom[3] );
   }

  /*
   * Destroy the dialog widget and NULLify its pointer.
   */
   gtk_widget_destroy( pWidgetDialogFind );
   pWidgetDialogFind = NULL;

  /*
   * Clear other find dialog state.
   */
   buttonWordAtCursorFlag  = FALSE;
   buttonRestoreCursorFlag = FALSE;

   return;
}

/*****************************************************************************
 * Called when the Find button of the Find dialog is clicked.
 * Either, a tag or module in a clist widget, or a string in the text widget, is sought.
 * The purpose of this function is to record what is being sought,
 * and defer the actual search to an appropriate function.
 *****************************************************************************/
void
FindDialogClickedFind( void )
{
   void FindDialogClickedFind___( void );

  /*
   * Prevent nesting major functions.
   */
   if ( IsAnyMajorFunctionBusy(TRUE) ) return;

  /*
   * For stability, serialize this function.
   */
   if ( busy_FindDialogClickedFind ) { DebugMsg( "FindDialogClickedFind() is busy." ); return; }
   busy_FindDialogClickedFind = TRUE;
   FindDialogClickedFind___();
   busy_FindDialogClickedFind = FALSE;
}
void
FindDialogClickedFind___( void )
{
   GString**	ppSought = NULL;

  /*
   * Determine which pSoughtX to use.
   */
   if ( soughtType == MENU_ITEM_FIND_TAG )
      ppSought = &pSoughtTag;
   else
   if ( soughtType == MENU_ITEM_FIND_TEXT )
      ppSought = &pSoughtText;
   else
   if ( soughtType == MENU_ITEM_FIND_MODULE )
      ppSought = &pSoughtModule;
   else
      g_assert( 0 );

  /*
   * Record what to find (for when the user does a subsequent search, eg Find Again).
   * Extract the text from the entry widget.
   */
   *ppSought = \
   g_string_new( gtk_editable_get_chars( GTK_EDITABLE(GTK_ENTRY(GTK_COMBO(pWidgetComboFind)->entry)),
                                         0, -1 ) );

  /*
   * Is what to find empty?
   */
   if ( ((*ppSought)->str)[0] == '\0' ) return;

  /*
   * Record what to find for the next creation of the find combo widget.
   */
   PrependComboDropDown( (*ppSought)->str,
                         ppGlistFindStrings );


  /*
   * Update the drop-down of the find combo.
   * (Helps the user who is repeatedly entering typos and wants to refer
   *  previous attempts.)
   */
   gtk_combo_set_popdown_strings( GTK_COMBO(pWidgetComboFind),
                                  *ppGlistFindStrings );

  /*
   * Defer to the appropriate find tag/text function.
   */
   if ( soughtType == MENU_ITEM_FIND_TAG )
   {
      SetSensitivityWhileBusy( FALSE );
      RecordCursorInTagHistory( _("(recorded position)" ));
      FindTagCheckMultipleMatches( (*ppSought)->str,
                                   SEEKING_ANY_TAG,
                                   NULL,
                                   widgetTagsClistSelectedRow,
                                   findExactTag,
                                   findCaseSensTag,
                                   autoSelectNotebookPage,
                                   _("Multiple tags match (press Enter or click Find for next one)." ));
      ScheduleUpdateFuncTree();
      SetSensitivityWhileBusy( TRUE );
   }
   else
   if ( soughtType == MENU_ITEM_FIND_TEXT )
   {
      //RecordCursorInTagHistory( _("(recorded position)" ));
      if ( ! findGlobal )
      {
         FindStringInTextWidget( (*ppSought)->str,
                                 TRUE,   /* wrap if necessary */
                                 FALSE,  /* loud */
                                 TRUE,   /* scroll/highlight match */
                                 NULL    /* don't care which line # */ );
      }
      else
      {
         SetSensitivityWhileBusy( FALSE );
         FindStringGlobal( (*ppSought)->str,
                           FALSE,	/* loud */
                           TRUE		/* stop search if find dialog is closed */  );
         SetSensitivityWhileBusy( TRUE );
      }
   }
   else
   if ( soughtType == MENU_ITEM_FIND_MODULE )
   {
      //RecordCursorInTagHistory( _("(recorded position)" ));
      SetSensitivityWhileBusy( FALSE );
      SearchClistWidget( (*ppSought)->str,
                         SEEKING_ANY_TAG,
                         NULL,
                         pWidgetClistModules,
                         widgetModulesClistSelectedRow,
                         findExactModule,
                         findCaseSensModule,
                         FALSE, /* be loud */
                         autoSelectNotebookPage,
                         TRUE	/* do select row */ );
      SetSensitivityWhileBusy( TRUE );
   }
   else
      g_assert( 0 );

   return;
}

/*****************************************************************************
 * Called when the "case sensitive" or "exact match" check button
 * of a find dialog is toggled.
 *****************************************************************************/
void
CheckButtonFindToggledBool( GtkWidget* pWidget,
                            gpointer   pVarBool )
{
  /*
   * Invert one of the global bools that control searching.
   */
#ifdef HYPERSRC_PEDANTIC
g_return_if_fail(    (pVarBool == &findExactTag)
                  || (pVarBool == &findExactModule)
                  || (pVarBool == &findCaseSensText)
                  || (pVarBool == &findCaseSensTag)
                  || (pVarBool == &findCaseSensModule) );
#endif

   if ( GTK_TOGGLE_BUTTON(pWidget)->active )
      *(gboolean*)pVarBool = TRUE;
   else
      *(gboolean*)pVarBool = FALSE;
}

/*****************************************************************************
 * Called when the "global" check button of a find dialog is toggled.
 * Toggle the global var "findGlobal".
 *****************************************************************************/
void
CheckButtonFindGlobalToggled( GtkWidget* pWidget,
                              gpointer   pData )
{
   if ( soughtType == MENU_ITEM_FIND_TEXT )
      findGlobal = !findGlobal;
}

/*****************************************************************************
 * Called when the "reverse" check button of a find dialog is toggled.
 * Toggle the global var "findReverse".
 *****************************************************************************/
void
CheckButtonFindReverseToggled( GtkWidget* pWidget,
                               gpointer   pData )
{
   if ( soughtType == MENU_ITEM_FIND_TEXT )
      findReverse = !findReverse;
}

/*****************************************************************************
 * Called when the "regex" check button of a find dialog is toggled.
 * Toggle the global var "regex".
 *****************************************************************************/
void
CheckButtonFindRegexToggled( GtkWidget* pWidget,
                             gpointer   pData )
{
   if ( soughtType == MENU_ITEM_FIND_TEXT )
      regex = !regex;
}

/******************************************************************************
 * add a translate function for I18N
 ******************************************************************************/
gchar*
MenuTranslate(const gchar* path,
        gpointer data)
{
    return (gchar*) _(path);
}
